package me.sealer.ssm.controller;

import lombok.extern.slf4j.Slf4j;
import me.sealer.ssm.constant.Dict;
import me.sealer.ssm.constant.ErrorCodeConstant;
import me.sealer.ssm.constant.RoleConstant;
import me.sealer.ssm.constant.SsmConstant;
import me.sealer.ssm.exception.SsmException;
import me.sealer.ssm.model.Permission;
import me.sealer.ssm.model.Role;
import me.sealer.ssm.model.RolePermission;
import me.sealer.ssm.service.PermissionService;
import me.sealer.ssm.service.RolePermissionService;
import me.sealer.ssm.service.RoleService;
import me.sealer.ssm.utils.MessageConverterUtil;
import me.sealer.ssm.utils.StringUtil;
import org.apache.shiro.authz.annotation.RequiresRoles;
import org.springframework.stereotype.Controller;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author sealer
 * @date 2016/09/27
 */
@Slf4j
@Controller
@RequestMapping("/rolePermissionMgmt")
@RequiresRoles(value = {RoleConstant.ROLE_ADMIN})
public class RolePermissionMgmtController {
    private final RoleService roleService;
    private final PermissionService permissionService;
    private final RolePermissionService rolePermissionService;

    public RolePermissionMgmtController(RoleService roleService, PermissionService permissionService, RolePermissionService rolePermissionService) {
        this.roleService = roleService;
        this.permissionService = permissionService;
        this.rolePermissionService = rolePermissionService;
    }

    @RequestMapping("/modifyPre/{roleName}")
    public ModelAndView modifyPre(@PathVariable(value = Dict.ROLE_NAME, required = false) String roleName, HttpServletRequest request) {
        if (StringUtil.isNullOrEmpty(roleName)) {
            String message = MessageConverterUtil.getMessage(request, Dict.ROLE_NAME);
            throw new SsmException(ErrorCodeConstant.SYSTEM_NOT_NULL, new Object[]{message});
        }
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.setViewName("rolePermissionModify");

        List<Permission> havingPermissions = permissionService.getPermissionsByRoleName(roleName);
        List<Integer> havingPermissionsIds = havingPermissions.stream().map(role -> role.getId()).collect(Collectors.toList());

        List<Permission> allPermissions = permissionService.getPermissions();
        modelAndView.addObject("allPermissions", allPermissions);
        modelAndView.addObject("havingPermissionsIds", havingPermissionsIds);
        modelAndView.addObject("roleName", roleName);

        return modelAndView;
    }

    @RequestMapping("/modify")
    @Transactional(rollbackFor = Exception.class)
    public ModelAndView modify(@RequestParam(value = Dict.ROLE_NAME, required = false) String roleName,
                               @RequestParam(value = "permissions", required = false) List<Integer> permissionsIds, HttpServletRequest request) {
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.setViewName("forward:modifyPre/" + roleName);

        if (StringUtil.isNullOrEmpty(roleName)) {
            String message = MessageConverterUtil.getMessage(request, Dict.ROLE_NAME);
            throw new SsmException(ErrorCodeConstant.SYSTEM_NOT_NULL, new Object[]{message});
        }

        if (permissionsIds == null || permissionsIds.size() == 0) {
            String message = MessageConverterUtil.getMessage(request, ErrorCodeConstant.PERMISSION_LIST_NULL);
            modelAndView.addObject(SsmConstant.RESULT_MESSAGE, message);
            return modelAndView;
        }

        Role role = roleService.getRoleByRoleName(roleName);
        if (role == null) {
            throw new SsmException(ErrorCodeConstant.ROLE_ROLE_NOT_EXISTS, new Object[]{roleName});
        }
        int roleId = role.getId();

        rolePermissionService.deleteByRoleId(roleId);

        permissionsIds.forEach(id -> {
            RolePermission rolePermission = new RolePermission(roleId, id);
            rolePermissionService.insert(rolePermission);
        });

        modelAndView.addObject(SsmConstant.RESULT_MESSAGE, ErrorCodeConstant.PERMISSION_MODIFY_SUCCESS.getMessage());
        return modelAndView;
    }
}
